package br.edu.unirn.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

public abstract class GenericDAO <T extends PersistDB>{
        
	private void change(T c, OperacaoDatabase op){
		EntityManager em = getEntityManager();
		em.getTransaction().begin();
		switch (op) {
			case INSERIR:
				em.persist(c);
				break;
			case ALTERAR:
				em.merge(c);
				break;
			case REMOVER:
				em.remove(c);
				break;
		}
		em.getTransaction().commit();
		//em.close();
	}
	
	public void create(T c){
		change(c, OperacaoDatabase.INSERIR);
	}
	public void update(T c){
		change(c, OperacaoDatabase.ALTERAR);
	}
	public void delete(T c){
		change(c, OperacaoDatabase.REMOVER);
	}

	public void remove(PersistDB obj){
                try{
                    EntityManager em = getEntityManager();
                    em.remove(em.getReference(obj.getClass(), obj.getId()));
                    em.getTransaction().commit();
                }catch(Exception e){
                    System.err.println(e);
                }
	}
	
	public T findByPrimaryKey(Long id){
		EntityManager em = getEntityManager();
		T c = em.find(getClassType(), id);
		return c;
	}
        
        @SuppressWarnings("unchecked")
	public <T extends PersistDB> T findByPrimaryKey(T obj){
                EntityManager em = getEntityManager();
		return (T)em.find(obj.getClass(), obj.getId());
	}
	
	public <T extends PersistDB> T findByPrimaryKey(Class<T> classe, long id){
                EntityManager em = getEntityManager();
		em.getTransaction().begin();	
                return (T)em.find(classe, id);
	}
	
	
	public List<T> findAll(){
		EntityManager em = getEntityManager();
		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<T> query = builder.createQuery(getClassType());
		TypedQuery<T> typedQuery = em.createQuery(query.select(query.from(getClassType())));
		List<T> c = typedQuery.getResultList();
		//em.close();
		return c;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findAllLike(String coluna,String valor){
		String tabela = getClassType().getSimpleName();
		String jpql = "from "+tabela+ " where "+coluna+" like :valor";
		EntityManager em = getEntityManager();
		Query q = em.createQuery(jpql);
		q.setParameter("valor", "%"+valor+"%");
		List<T> retorno = q.getResultList();
		//em.close();
		return retorno;
	}
        
	protected EntityManager getEntityManager(){
		return Database.getInstance();
	}
	
	public abstract Class<T> getClassType();
}

enum OperacaoDatabase {
	INSERIR,ALTERAR,REMOVER;
}